
package jason.stdlib;

import jason.*;
import jason.asSemantics.*;
import jason.asSyntax.*;
import jason.asSyntax.directives.Import;

import java.io.File;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * <p>
 * Internal action: <b><code>.import</code></b>.
 * 
 * <p>
 * Description: import a module dynamically specified by its URL.<br>
 * 
 * <p>
 * Parameters:
 * <ul>
 * <li>+ [name] (atom): optional name of the module, used only for debugging.<br/>
 * <li>+ URL (string): the URL of the file containing the description of the module.
 * </ul>
 * 
 * <p>
 * Examples:
 * <ul>
 * 
 * <li><code>.import(phone,"http://www.example.com/phone.aslm")</code></li>
 * 
 * <li><code>.import("file:///home/user/service.aslm")</code></li>
 * 
 * </ul>
 */
public class import_module extends DefaultInternalAction {
	private static Logger logger = Logger.getLogger(Import.class.getName());
	
	public static final String SHORT_NAME = "jason.stdlib.import";
	public static final String FULL_NAME = "jason.stdlib.import_module";
	
	private static InternalAction singleton = null;
    public static InternalAction create() {
        if (singleton == null) 
            singleton = new import_module();
        return singleton;
    }
	
	@Override
	public int getMinArgs() {
		return 1;
	}
	
	@Override
	public int getMaxArgs() {
		return 2;
	}
	
	@Override
	protected void checkArguments(Term[] args) throws JasonException {
		super.checkArguments(args); // check number of arguments
		if (args.length == 1) { // 1 argument: URL
			if (!args[0].isString()) throw JasonException.createWrongArgument(this, "the URL must be specified as a string");
		} else { // 2 arguments: name, URL
			if (!args[0].isAtom()) throw JasonException.createWrongArgument(this, "the name of the module must be an atom");
			if (!args[1].isString()) throw JasonException.createWrongArgument(this, "the URL must be specified as a string");
		}
	}
	
	@Override
	public Object execute(TransitionSystem ts, Unifier un, Term[] args) throws Exception {
		checkArguments(args);
		
		String name;
		String url;
		if (args.length == 1) { // 1 argument: URL
			url = ((StringTerm)args[0]).getString();
			name = (new File(url)).getName().replaceFirst("\\.[^.]*$", "");
		} else { // 2 arguments: name, URL
			name = ((Atom)args[0]).getFunctor();
			url = ((StringTerm)args[1]).getString();
		}
		
		Agent ag = ts.getAg();
		
		name = ag.getUniqueModuleName('_' + name);
		
		try {
			logger.fine("Importing module \"" + url + "\" with name '" + name + "' to agent '" + ag + "'.");
			Import.importModule(ag, name, url, "");
			logger.fine("Module '" + name + "' imported with actual modules to import: " + ag.getImportQueue());
			Import.importModules(ag, true);
			return true;
		} catch (RuntimeException e) {
			Throwable exp = e;
			if (e.getCause() != null) {
				exp = e.getCause();
			}
			logger.log(Level.WARNING, "Error importing module \"" + url + "\": " + exp.getMessage(), exp);
			return false;
		}
	}
}
